package com.kxmall.web.controller.huishouapp;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.kxmall.categorize.domain.vo.HsWasteCategorizeVo;
import com.kxmall.categorize.service.IHsWasteCategorizeService;
import com.kxmall.common.annotation.Log;
import com.kxmall.common.annotation.RepeatSubmit;
import com.kxmall.common.core.controller.BaseAppController;
import com.kxmall.common.core.domain.PageQuery;
import com.kxmall.common.core.domain.R;
import com.kxmall.common.core.domain.model.LoginUser;
import com.kxmall.common.core.page.TableDataInfo;
import com.kxmall.common.core.validate.AddGroup;
import com.kxmall.common.core.validate.EditGroup;
import com.kxmall.common.enums.BillDetailEnum;
import com.kxmall.common.enums.BusinessType;
import com.kxmall.common.enums.DeviceType;
import com.kxmall.common.exception.ServiceException;
import com.kxmall.common.helper.LoginHelper;
import com.kxmall.huishou.domain.HsAppointmentOrder;
import com.kxmall.huishou.domain.HsSettlementOrder;
import com.kxmall.huishou.domain.HsUserWaste;
import com.kxmall.huishou.domain.bo.HsAppointmentOrderBo;
import com.kxmall.huishou.domain.bo.HsSettlementOrderBo;
import com.kxmall.huishou.domain.bo.HsUserWasteBo;
import com.kxmall.huishou.domain.bo.HsWasteNewsBo;
import com.kxmall.huishou.domain.vo.HsAppointmentOrderVo;
import com.kxmall.huishou.domain.vo.HsSettlementOrderVo;
import com.kxmall.huishou.domain.vo.HsUserWasteVo;
import com.kxmall.huishou.domain.vo.HsWasteSiteVo;
import com.kxmall.huishou.service.IHsAppointmentOrderService;
import com.kxmall.huishou.service.IHsSettlementOrderService;
import com.kxmall.huishou.service.IHsUserWasteService;
import com.kxmall.order.domain.vo.KxStoreOrderVo;
import com.kxmall.system.domain.SysNotice;
import com.kxmall.user.domain.KxUser;
import com.kxmall.user.domain.bo.KxUserBillBo;
import com.kxmall.user.domain.bo.KxUserBo;
import com.kxmall.user.domain.vo.KxUserVo;
import com.kxmall.user.service.IUserBillService;
import com.kxmall.web.controller.notice.service.IKxNoticetService;
import com.kxmall.web.controller.user.service.IKxAppUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 预约订单
 *
 * @author lf
 * @date 2023-12-01
 */
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/appOrder/app")
public class HsAppOrderController extends BaseAppController {

    /**
     * 高德地图API密钥
     * 可以在application.yml中配置：kxmall.amap.api-key
     * 如果没有配置，将使用默认值（需要替换为真实的API密钥）
     */
    @Value("${kxmall.amap.api-key:your_amap_api_key}")
    private String amapApiKey;

    private final IHsAppointmentOrderService iHsAppointmentOrderService;
    private final IHsUserWasteService iHsUserWasteService;
    private final IHsSettlementOrderService iHsSettlementOrderService;
    private final IKxNoticetService iKxNoticetService;
    private final IKxAppUserService iKxAppUserService;
    private final IUserBillService iUserBillService;

    /**
     * 查询订单列表
     */
    @GetMapping("/getOrderPageList")
    public TableDataInfo<HsAppointmentOrderVo> getOrderPageLists(HsAppointmentOrderBo bo, PageQuery pageQuery){

        if(bo == null){
            bo = new HsAppointmentOrderBo();
        }
        bo.setUserId(getAppLoginUser().getUserId());
        if(bo.getStatus() != null && (bo.getStatus() < 0 || bo.getStatus() > 9)){
            bo.setStatus(null);
        }
        pageQuery.setOrderByColumn("create_time");
        pageQuery.setIsAsc("desc");

        return iHsAppointmentOrderService.queryPageLists(bo,pageQuery);
    }

    /**
     * 获取回收预约订单详细信息
     *
     * @param id 主键
     */
    @GetMapping("/{id}")
    public R<HsAppointmentOrderVo> getInfoById(@NotNull(message = "主键不能为空") @PathVariable Long id) {

        HsAppointmentOrderVo hsAppointmentOrderVo = iHsAppointmentOrderService.queryById(id);
        Long userId = getAppLoginUser().getUserId();

        if(hsAppointmentOrderVo != null){
            if(hsAppointmentOrderVo.getUserId().longValue() != userId.longValue()){

                return R.fail("订单信息与用户不匹配");
            }
            HsUserWasteBo hsUserWasteBo = new HsUserWasteBo();
            hsUserWasteBo.setOrderId(hsAppointmentOrderVo.getId());
            hsUserWasteBo.setOrderType(0L);
            List<HsUserWasteVo> hsUserWasteVoList = iHsUserWasteService.queryList(hsUserWasteBo);
            hsAppointmentOrderVo.setHsUserWasteVoList(hsUserWasteVoList);
        }
        return R.ok(hsAppointmentOrderVo);
    }


    /**
     * 新增回收预约订单信息
     */
    @Log(title = "新增回收预约订单信息", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping("/add")
    public R<Void> add(@Validated(AddGroup.class) @RequestBody HsAppointmentOrderBo bo) {
        // 使用修改后的安全方法获取用户信息，防止ThreadLocal污染导致的串号
        LoginUser loginUser = getAppLoginUser();
        Long userId = loginUser.getUserId();

        // 记录关键信息用于问题排查和串号检测
        String tokenPrefix = cn.dev33.satoken.stp.StpUtil.getTokenValue().substring(0, Math.min(10, cn.dev33.satoken.stp.StpUtil.getTokenValue().length()));
        log.info("订单创建开始 - 用户ID: {}, Token前缀: {}, LoginId: {}, 线程: {}, 时间: {}",
            userId,
            tokenPrefix + "...",
            cn.dev33.satoken.stp.StpUtil.getLoginIdAsString(),
            Thread.currentThread().getName(),
            System.currentTimeMillis());

        bo.setOrderNo("HSYY"+ DateFormatUtils.format(System.currentTimeMillis(),"yyyyMMddHHmmssSSS"));
        bo.setUserId(userId);
        bo.setStatus(0l);
        bo.setRiderId(null);
        bo.setTakingTime(null);
        bo.setArriveTime(null);
        bo.setCompleteTime(null);

        // 如果经纬度为空，尝试通过高德地图API解析获取
        if (bo.getLongitude() == null || bo.getLatitude() == null) {
            //log.info("订单经纬度为空，开始地址解析。省份：{}，城市：{}，区县：{}，详细地址：{}",bo.getProvince(), bo.getCity(), bo.getCounty(), bo.getAddress());

            try {
                java.math.BigDecimal[] coordinates = getCoordinatesByAmap(bo.getProvince(), bo.getCity(), bo.getCounty(), bo.getAddress());
                if (coordinates != null && coordinates.length == 2) {
                    bo.setLongitude(coordinates[0]);
                    bo.setLatitude(coordinates[1]);
                    //log.info("✅ 高德地图API解析成功！经度：{}，纬度：{}", coordinates[0], coordinates[1]);
                } else {
                    // 临时解决方案：如果API解析失败，使用默认坐标
                    log.warn("❌ 高德地图API解析失败，使用默认坐标");
                    if ("乌海市".equals(bo.getCity()) || (bo.getCity() != null && bo.getCity().contains("乌海"))) {
                        bo.setLongitude(new java.math.BigDecimal("106.794249"));
                        bo.setLatitude(new java.math.BigDecimal("39.655388"));
                        //log.info("🏠 使用乌海市默认坐标：经度：106.794249，纬度：39.655388");
                    } else {
                        bo.setLongitude(new java.math.BigDecimal("116.404"));
                        bo.setLatitude(new java.math.BigDecimal("39.915"));
                        //log.info("🏠 使用北京默认坐标：经度：116.404，纬度：39.915");
                    }
                    // 如果需要严格验证，取消注释下面这行
                    // return R.fail("地址解析失败，请检查地址信息是否正确或稍后重试");
                }
            } catch (Exception e) {
                log.error("地址解析异常", e);
                // 临时解决方案：异常时也使用默认坐标
                log.warn("⚠️ 地址解析异常，使用默认坐标");
                if ("乌海市".equals(bo.getCity()) || (bo.getCity() != null && bo.getCity().contains("乌海"))) {
                    bo.setLongitude(new java.math.BigDecimal("106.794249"));
                    bo.setLatitude(new java.math.BigDecimal("39.655388"));
                    //log.info("🏠 异常处理-使用乌海市默认坐标：经度：106.794249，纬度：39.655388");
                } else {
                    bo.setLongitude(new java.math.BigDecimal("116.404"));
                    bo.setLatitude(new java.math.BigDecimal("39.915"));
                    //log.info("🏠 异常处理-使用北京默认坐标：经度：116.404，纬度：39.915");
                }
                // 如果需要严格验证，取消注释下面这行
                // return R.fail("地址解析服务异常，请稍后重试");
            }
        }

        return toAjax(iHsAppointmentOrderService.insertByBo(bo));
    }

    /**
     * 修改回收预约订单信息
     */
    @Log(title = "回收预约订单信息", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping("/edit")
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody HsAppointmentOrderBo bo) {
        bo.setUserId(getAppLoginUser().getUserId());
        bo.setStatus(0l);
        return toAjax(iHsAppointmentOrderService.updateByBo(bo));
    }

    /**
     * 取消预约订单信息
     */
    @Log(title = "取消预约订单信息", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping("/cancelById")
    public R<Void> cancelById(@RequestBody HsAppointmentOrderBo bo) {
        if(bo.getId() == null ){
            return R.fail();
        }

        Long userId = getAppLoginUser().getUserId();

        HsAppointmentOrderVo hsAppointmentOrderVo = iHsAppointmentOrderService.queryById(bo.getId());
        if(hsAppointmentOrderVo == null || hsAppointmentOrderVo.getStatus() != 0 || hsAppointmentOrderVo.getUserId().longValue() != userId.longValue() ){
            return R.fail("订单状态已改变不允许取消");
        }

        return toAjax(iHsAppointmentOrderService.cancelById(bo.getId()));
    }

    /**
     * 删除回收预约订单子信息
     *
     * @param ids 主键串
     */
    @Log(title = "删除回收预约订单子信息", businessType = BusinessType.DELETE)
    @DeleteMapping("/delHsWasteById/{ids}")
    public R<Void> removeHsWasteById(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        Long userId = getAppLoginUser().getUserId();
        return toAjax(iHsUserWasteService.deleteWithValidByIds(Arrays.asList(ids), true, userId, 0l));
    }


    /**
     * 查询结算订单列表
     */
    @GetMapping("/getSettlementOrderPageList")
    public TableDataInfo<HsSettlementOrderVo> getSettlementOrderPageList(HsSettlementOrderBo bo, PageQuery pageQuery){

        if(bo == null){
            bo = new HsSettlementOrderBo();
        }
        bo.setUserId(getAppLoginUser().getUserId());
        if(bo.getStatus() != null && (bo.getStatus() < 0 || bo.getStatus() > 6)){
            bo.setStatus(null);
        }
        pageQuery.setOrderByColumn("create_time");
        pageQuery.setIsAsc("desc");

        return iHsSettlementOrderService.queryPageList(bo,pageQuery);
    }


    /**
     * 获取结算订单详细信息
     *
     * @param id 主键
     */
    @GetMapping("/getSettlementOrderById/{id}")
    public R<HsSettlementOrderVo> getSettlementOrderById(@NotNull(message = "主键不能为空") @PathVariable Long id) {

        HsSettlementOrderVo hsSettlementOrderVo = iHsSettlementOrderService.queryById(id);
        Long userId = getAppLoginUser().getUserId();

        if(hsSettlementOrderVo != null){
            if(hsSettlementOrderVo.getUserId().longValue() != userId.longValue()){

                return R.fail("订单信息与用户不匹配");
            }
            HsUserWasteBo hsUserWasteBo = new HsUserWasteBo();
            hsUserWasteBo.setOrderId(id);
            hsUserWasteBo.setOrderType(1L);
            List<HsUserWasteVo> hsUserWasteVoList = iHsUserWasteService.queryList(hsUserWasteBo);
            hsSettlementOrderVo.setHsUserWasteVoList(hsUserWasteVoList);
        }
        return R.ok(hsSettlementOrderVo);
    }


    /**
     * 处理结算订单
     */
    @Log(title = "处理结算订单", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @GetMapping("/dealSettleOrderById")
    public R<Void> dealSettleOrderById(HsSettlementOrderBo bo) {
        if(bo.getId() == null ){
            return R.fail("参数错误！");
        }

        Long userId = getAppLoginUser().getUserId();

        HsSettlementOrderVo hsSettlementOrderVo = iHsSettlementOrderService.queryById(bo.getId());
        if(hsSettlementOrderVo == null || hsSettlementOrderVo.getUserId().longValue() != userId.longValue() ){
            return R.fail("订单不存在！");
        }

        SysNotice sysNotice = null;

        if(bo.getStatus() == null){
            return R.fail("操作状态为空！");
        }else if(bo.getStatus().longValue() == 1l || bo.getStatus().longValue() == 2l){
            if(hsSettlementOrderVo.getStatus().longValue() != 0l){
                return R.fail("该状态无法确认信息！");
            }
            //新建通知消息，发给回收员
            sysNotice = new SysNotice();
            if(bo.getStatus().longValue() == 1l){
                sysNotice.setNoticeTitle("结算订单"+hsSettlementOrderVo.getOrderNo()+"用户已确认，等待支付！");
                sysNotice.setNoticeContent("结算订单"+hsSettlementOrderVo.getOrderNo()+"用户已确认，等待支付！");
            }else {
                sysNotice.setNoticeTitle("结算订单"+hsSettlementOrderVo.getOrderNo()+"用户已取消结算，等待处理！");
                sysNotice.setNoticeContent("结算订单"+hsSettlementOrderVo.getOrderNo()+"用户已取消结算，等待处理！");
            }

            sysNotice.setNoticeType("1");
            sysNotice.setStatus("0");
            sysNotice.setUserId(hsSettlementOrderVo.getRiderId());
            sysNotice.setUserType(2);

        }else if(bo.getStatus().longValue() == 4l || bo.getStatus().longValue() == 5l){
            if(hsSettlementOrderVo.getStatus().longValue() != 3l){
                return R.fail("该状态无法确认支付！");
            }

            //新建通知消息，发给回收员
            sysNotice = new SysNotice();
            if(bo.getStatus().longValue() == 4l){
                sysNotice.setNoticeTitle("结算订单"+hsSettlementOrderVo.getOrderNo()+"用户已确认支付，订单完成！");
                sysNotice.setNoticeContent("结算订单"+hsSettlementOrderVo.getOrderNo()+"用户已确认支付，订单完成！");
            }else {
                sysNotice.setNoticeTitle("结算订单"+hsSettlementOrderVo.getOrderNo()+"用户确认支付失败，等待处理！");
                sysNotice.setNoticeContent("结算订单"+hsSettlementOrderVo.getOrderNo()+"用户确认支付失败，等待处理！");
            }

            sysNotice.setNoticeType("1");
            sysNotice.setStatus("0");
            sysNotice.setUserId(hsSettlementOrderVo.getRiderId());
            sysNotice.setUserType(2);

        }else {
            return R.fail("操作状态错误！");
        }

        HsSettlementOrder order = new HsSettlementOrder();
        order.setId(bo.getId());
        order.setStatus(bo.getStatus());

        boolean flag = iHsSettlementOrderService.updateById(order);

        //如果结算成功，则修改预约订单状态
        if(flag && order.getStatus().longValue() == 4l){
            HsAppointmentOrder appointmentOrder = new HsAppointmentOrder();
            appointmentOrder.setId(hsSettlementOrderVo.getAppointOrderId());
            appointmentOrder.setUserId(userId);
            appointmentOrder.setStatus(5l);
            appointmentOrder.setCompleteTime(new Date());
            iHsAppointmentOrderService.dealOrderByRider(appointmentOrder);

            //如果是平台支付，则需要给用户增加余额
            if(hsSettlementOrderVo.getPayType() == 0){
                KxUserVo kxUserVo = iKxAppUserService.queryById(userId);
                KxUserBo kxUserBo = new KxUserBo();
                kxUserBo.setUid(userId);
                kxUserBo.setNowMoney(kxUserVo.getNowMoney().add(hsSettlementOrderVo.getAmountTal()));
                iKxAppUserService.updateByBo(kxUserBo);

                //保存账户流水
                KxUserBillBo kxUserBillBo = new KxUserBillBo();
                kxUserBillBo.setUid(userId);
                kxUserBillBo.setLinkId(hsSettlementOrderVo.getId()+"");
                kxUserBillBo.setPm(1);
                kxUserBillBo.setTitle("卖出废品收入"+hsSettlementOrderVo.getAmountTal()+"元");
                kxUserBillBo.setCategory(BillDetailEnum.CATEGORY_1.getValue());
                kxUserBillBo.setType(BillDetailEnum.TYPE_1.getValue());
                kxUserBillBo.setNumber(hsSettlementOrderVo.getAmountTal());
                kxUserBillBo.setBalance(kxUserBo.getNowMoney());
                kxUserBillBo.setStatus(1);
                kxUserBillBo.setIsDel(0);

                iUserBillService.insertByBo(kxUserBillBo);

            }
        }

        //保存通知信息
        try {
            if(flag && sysNotice != null){
                iKxNoticetService.save(sysNotice);
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        return toAjax(flag);
    }

    /**
     * 删除回收预约订单信息
     */
    @Log(title = "删除回收预约订单信息", businessType = BusinessType.DELETE)
    @RepeatSubmit()
    @DeleteMapping("/appointmentOrder/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(iHsAppointmentOrderService.deleteWithValidByIds(Arrays.asList(ids), true));
    }

    /**
     * 通过高德地图API获取经纬度坐标
     *
     * @param province 省份
     * @param city 城市
     * @param county 区县
     * @param address 详细地址
     * @return 经纬度数组 [经度, 纬度]，失败返回null
     */
    private java.math.BigDecimal[] getCoordinatesByAmap(String province, String city, String county, String address) {
        try {
            // 检查API密钥是否配置
            //log.info("🔑 当前配置的API密钥：{}", amapApiKey);
            if ("your_amap_api_key".equals(amapApiKey) || amapApiKey == null || amapApiKey.trim().isEmpty()) {
                log.warn("❌ 高德地图API密钥未配置或无效，请在配置文件中设置 kxmall.amap.api-key");
                return null;
            }

            //log.info("🚀 开始调用高德地图API，密钥：{}...", amapApiKey.substring(0, Math.min(8, amapApiKey.length())));

            // 构建完整地址
            StringBuilder fullAddress = new StringBuilder();
            if (province != null && !province.trim().isEmpty()) {
                fullAddress.append(province.trim());
            }
            if (city != null && !city.trim().isEmpty()) {
                fullAddress.append(city.trim());
            }
            if (county != null && !county.trim().isEmpty()) {
                fullAddress.append(county.trim());
            }
            if (address != null && !address.trim().isEmpty()) {
                fullAddress.append(address.trim());
            }

            String addressStr = fullAddress.toString();
            if (addressStr.isEmpty()) {
                return null;
            }

            // 构建高德地图地理编码API请求URL
            String encodedAddress = java.net.URLEncoder.encode(addressStr, "UTF-8");
            String apiUrl = String.format("https://restapi.amap.com/v3/geocode/geo?key=%s&address=%s",
                    amapApiKey, encodedAddress);

            //log.info("高德地图API请求URL：{}", apiUrl.replace(amapApiKey, "***"));

            // 发送HTTP请求
            String response = sendHttpRequest(apiUrl);
            //log.info("高德地图API响应：{}", response);

            if (response == null || response.trim().isEmpty()) {
                log.warn("高德地图API返回空响应");
                return null;
            }

            // 解析响应结果
            JSONObject jsonResponse = JSON.parseObject(response);
            String status = jsonResponse.getString("status");

            if (!"1".equals(status)) {
                log.warn("高德地图API返回错误，状态：{}，信息：{}", status, jsonResponse.getString("info"));
                return null;
            }

            JSONArray geocodes = jsonResponse.getJSONArray("geocodes");
            if (geocodes == null || geocodes.isEmpty()) {
                log.warn("高德地图API未找到匹配的地址：{}", addressStr);
                return null;
            }

            JSONObject geocode = geocodes.getJSONObject(0);
            String location = geocode.getString("location");
            if (location == null || location.trim().isEmpty()) {
                log.warn("高德地图API返回的坐标为空");
                return null;
            }

            String[] coords = location.split(",");
            if (coords.length != 2) {
                log.warn("高德地图API返回的坐标格式错误：{}", location);
                return null;
            }

            java.math.BigDecimal longitude = new java.math.BigDecimal(coords[0]);
            java.math.BigDecimal latitude = new java.math.BigDecimal(coords[1]);

            //log.info("🎯 高德地图地理编码成功！");
            //log.info("📍 输入地址：{}", addressStr);
            //log.info("📍 解析结果：经度：{}，纬度：{}", longitude, latitude);
            //log.info("📍 坐标位置：{}", geocode.getString("formatted_address"));

            return new java.math.BigDecimal[]{longitude, latitude};

        } catch (Exception e) {
            log.error("高德地图地理编码异常", e);
            return null;
        }
    }

    /**
     * 发送HTTP请求
     */
    private String sendHttpRequest(String urlStr) {
        try {
            java.net.URL url = new java.net.URL(urlStr);
            java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(10000);
            connection.setRequestProperty("User-Agent", "Mozilla/5.0");

            int responseCode = connection.getResponseCode();
            if (responseCode != java.net.HttpURLConnection.HTTP_OK) {
                log.error("HTTP请求失败，响应码：{}", responseCode);
                return null;
            }

            java.io.BufferedReader reader = new java.io.BufferedReader(
                    new java.io.InputStreamReader(connection.getInputStream(), "UTF-8"));
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            reader.close();
            connection.disconnect();

            return response.toString();

        } catch (Exception e) {
            log.error("HTTP请求异常", e);
            return null;
        }
    }



}
